home *** CD-ROM | disk | FTP | other *** search
/ APDL Eductation Resources / APDL Eductation Resources.iso / programs / astronomy / skyview / !SkyView / c / UserObj < prev   
Encoding:
Text File  |  1993-08-26  |  24.8 KB  |  721 lines

  1. /********************************************************/
  2. /*              UserObj Module for SkyView              */
  3. /*                                                      */
  4. /*                  (c)1992 N P Hawkes                  */
  5. /*                                                      */
  6. /*      Displays User Object at specified RA & Dec      */
  7. /********************************************************/
  8.  
  9. #include "menu.h"
  10. #include "dbox.h"
  11. #include "bbc.h"
  12. #include "wimpt.h"
  13. #include "dbox.h"
  14. #include "string.h"
  15. #include "event.h"
  16. #include "res.h"
  17. #include "resspr.h"
  18. #include "werr.h"
  19. #include "os.h"
  20.  
  21. #include "sv_header.h"
  22. #include "userobj.h"
  23. #include "radec.h"
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27.  
  28. /********************************************************/
  29. /*                     Constants                        */
  30. /********************************************************/
  31. #define DISP_NAME  ">User obj." /*Entry in Display menu.*/
  32. #define SEL_NAME   " User obj." /*Entry in Select menu. */
  33. #define FILE_NAME    "UserData" /* Name of disc file.   */
  34. #define DISPBOX_NAME "UserDisp" /* Name of Disp dbox.   */
  35. #define SPRITE_NAME  "userobj"  /*Name of UserObj Sprite*/
  36.  
  37. #define HORALT (REAL)0.0044      /* Altitude of horizon.*/
  38.  
  39. /* Length of one line of description (inc. \0 at end):  */
  40. #define USEROBJ_TEXTLEN 31
  41.  
  42. /* Constants relating to Display dialogue box.          */
  43. enum {
  44.   box_destroy = -1, /* Response cancelling the dbox.    */
  45.   ok_butt     =  0, /* OK button.                       */
  46.   cancel_butt,      /* Cancel button.                   */
  47.   show_butt,        /* Show Defaults button.            */
  48.   set_butt,         /* Set Defaults button.             */
  49.   rah_field,        /* Field for hour part of RA.       */
  50.   ram_field,        /* Field for minute part of RA.     */
  51.   decd_field,       /* Field for degree part of Dec.    */
  52.   decm_field,       /* Field for minute part of Dec.    */
  53.   ns_field,         /* Field for 'N' or 'S'.            */
  54.   ns_butt,          /* Button to toggle between N & S.  */
  55.   rah_tu  = 10,     /* Increment tens in rah_field.     */
  56.   rah_td,           /* Decrement tens in rah_field.     */
  57.   rah_uu,           /* Increment units in rah_field.    */
  58.   rah_ud,           /* Decrement units in rah_field.    */
  59.   ram_tu  = 14,     /* Increment tens in ram_field.     */
  60.   ram_td,           /* Decrement tens in ram_field.     */
  61.   ram_uu,           /* Increment units in ram_field.    */
  62.   ram_ud,           /* Decrement units in ram_field.    */
  63.   decd_tu = 18,     /* Increment tens in decd_field.    */
  64.   decd_td,          /* Decrement tens in decd_field.    */
  65.   decd_uu,          /* Increment units in decd_field.   */
  66.   decd_ud,          /* Decrement units in decd_field.   */
  67.   decm_tu = 22,     /* Increment tens in decm_field.    */
  68.   decm_td,          /* Decrement tens in decm_field.    */
  69.   decm_uu,          /* Increment units in decm_field.   */
  70.   decm_ud,          /* Decrement units in decm_field.   */
  71.   text1_field = 26, /* Field for first line of text.    */
  72.   text2_field,      /* Field for 2nd line of text.      */
  73.   text3_field       /* Field for 3rd line of text.      */
  74. };
  75.  
  76. /********************************************************/
  77. /*                New types of variable.                */
  78. /********************************************************/
  79. /* Structure describing data on show in Display dbox.   */
  80. typedef struct {
  81.   int  rah;         /* Hour part of Right Ascension.    */
  82.   int  ram;         /* Minute part of Right Ascension.  */
  83.   int  decd;        /* Degree part of Declination.      */
  84.   int  decm;        /* Minute part of Declination.      */
  85.   BOOL isn;         /* TRUE if Dec is North.            */
  86.   char text1[USEROBJ_TEXTLEN];   /* First line of text. */
  87.   char text2[USEROBJ_TEXTLEN];   /* 2nd line of text.   */
  88.   char text3[USEROBJ_TEXTLEN];   /* 3rd line of text.   */
  89. } userobjstr;
  90.  
  91. /********************************************************/
  92. /*                  Global Variables                    */
  93. /********************************************************/
  94. static BOOL display_flag = FALSE;  /* 'Enabled' flag.   */
  95. /* Flag indicating whether a Rebuild Request is pending:*/
  96. static BOOL request_pending  = FALSE;
  97. static int moduleid;               /* Module ID.        */
  98. static sprite_id spr_id;           /* For Userobj sprite*/
  99.  
  100. static dbox d_disp;                /* Display dbox.     */
  101. static userobjstr current_data = { /* Current data.     */
  102.   0,
  103.   0,
  104.   0,
  105.   0,
  106.   TRUE,
  107.   "",
  108.   "<Untitled>",
  109.   ""
  110. };
  111.  
  112. static REAL ra;         /* Current RA.                  */
  113. static REAL dec;        /* Current Dec.                 */
  114.  
  115. static int  horiz_id;   /* Current ID in Horiz window.  */
  116. static int  vert_id;    /* Current ID in Vert window.   */
  117.  
  118. static int addon[4] =   /* For incrementing / decrement-*/
  119. { 10,                   /* ing numbers in Display dbox. */
  120.  -10,
  121.    1,
  122.   -1 };
  123.  
  124. /********************************************************/
  125. /*                 Function Prototypes                  */
  126. /********************************************************/
  127. static BOOL read_discfile(userobjstr *ptr);
  128. static void userobj_radec(userobjstr *ptr, REAL *raptr, REAL *decptr);
  129. static BOOL write_discfile(userobjstr *ptr);
  130. static void userobj_buildfn(void);
  131. static BOOL userobj_displayfn(BOOL *enabptr);
  132. static void load_dispbox(userobjstr *ptr);
  133. static void read_dispbox(userobjstr *ptr);
  134. static BOOL dispbox_buttons(void);
  135. static BOOL copy_data(userobjstr *ptr1, userobjstr *ptr2);
  136. static void dispbox_databutts(int response);
  137. static os_error *userobj_plotfn(int x, int y, int id);
  138. static void userobj_infofn(int id);
  139. static void userobj_selectfn(selectfn_reasoncode reason);
  140. static void selection_details(void);
  141.  
  142. /********************************************************/
  143. /*                Initialisation Function               */
  144. /********************************************************/
  145. BOOL userobj_initfn(int moduleno, modulestr *userobj)
  146. {
  147.   sprite_id nametype_id;
  148.   os_error *errptr;
  149.  
  150. /* Record the module number of this module.             */
  151.   moduleid = moduleno;
  152.  
  153. /* Attempt to read default settings from disc.  If      */
  154. /* error, just carry on with hard-wired settings.       */
  155.   read_discfile(¤t_data);
  156. /* Set the RA and Dec to correspond with these values.  */
  157.   userobj_radec(¤t_data, &ra, &dec);
  158.  
  159. /* Initialise sprite identifier.                        */
  160. /* First build a name-type sprite id.                   */
  161.   nametype_id.s.name = SPRITE_NAME;
  162.   nametype_id.tag    = sprite_id_name;
  163. /* Then get the sprite's address & put it in the global */
  164. /* sprite identifier spr_id.                            */
  165.   errptr = sprite_select_rp(resspr_area(), &nametype_id, &spr_id.s.addr);
  166.   if (errptr != NULL) return FALSE;
  167. /* Finally tag the identifier spr_id as address-type.   */
  168.   spr_id.tag = sprite_id_addr;
  169.  
  170. /* Fill in the fields of the modulestr.                 */
  171.   userobj->buildfn  = userobj_buildfn;
  172.   userobj->selectfn = userobj_selectfn;
  173.   userobj->dispfn   = userobj_displayfn;
  174.   userobj->infofn   = userobj_infofn;
  175.   userobj->initial  = display_flag;
  176.   userobj->display_entry = DISP_NAME;
  177.   userobj->display_menu  = NULL;
  178.   userobj->select_entry  = SEL_NAME;
  179.   userobj->select_menu   = NULL;
  180.  
  181.   return TRUE;
  182. }
  183.  
  184. /*------------------------------------------------------*/
  185. /*  Function to read default values of RA, Dec and text */
  186. /*  from disc file.  Returns TRUE if data read OK.  If  */
  187. /*    error, returns FALSE and leaves *ptr unchanged.   */
  188. /*------------------------------------------------------*/
  189. static BOOL read_discfile(userobjstr *ptr)
  190. {
  191.   userobjstr tempstr[1];
  192.   FILE *fileptr;
  193.   size_t numread;
  194.  
  195. /* Open disc file for reading binary.                   */
  196.   fileptr = res_openfile(FILE_NAME, "rb");
  197.   if (fileptr == NULL) return FALSE;
  198.  
  199. /* Try to read one userobjstr from file.                */
  200.   numread = fread((void *)tempstr, sizeof(userobjstr), 1, fileptr);
  201.  
  202. /* Close disc file.  Fatal error if it won't close.     */
  203.   if (fclose(fileptr) != 0)
  204.     werr(FATAL, "UserObj Error: Can't close Default file");
  205.  
  206. /* If attempt to read failed, return FALSE now.         */
  207.   if (numread != 1) return FALSE;
  208.  
  209. /* All OK, so transfer data to *ptr and return TRUE.    */
  210.   *ptr = tempstr[0];
  211.   return TRUE;
  212. }
  213.  
  214. /*------------------------------------------------------*/
  215. /* Function to write to disc the values of RA, Dec and  */
  216. /*   text pointed to by ptr.  Returns FALSE if error.   */
  217. /*------------------------------------------------------*/
  218. static BOOL write_discfile(userobjstr *ptr)
  219. {
  220.   userobjstr tempstr[1];
  221.   FILE *fileptr;
  222.   size_t numwritten;
  223.  
  224. /* Copy data into array variable.                       */
  225.   tempstr[0] = *ptr;
  226.  
  227. /* Open disc file for writing binary.                   */
  228.   fileptr = res_openfile(FILE_NAME, "wb");
  229.   if (fileptr == NULL) return FALSE;
  230.  
  231. /* Try to write one userobjstr to file.                 */
  232.   numwritten = fwrite((void *)tempstr, sizeof(userobjstr), 1, fileptr);
  233.  
  234. /* Close disc file.  Fatal error if it won't close.     */
  235.   if (fclose(fileptr) != 0)
  236.     werr(FATAL, "UserObj Error: Can't close Default file");
  237.  
  238. /* Return sucess or failure.                            */
  239.   return (numwritten == 1);
  240. }
  241.  
  242. /*------------------------------------------------------*/
  243. /*  Function to calculate the RA and Dec from the data  */
  244. /*                 pointed to by ptr.                   */
  245. /*------------------------------------------------------*/
  246. static void userobj_radec(userobjstr *ptr, REAL *raptr, REAL *decptr)
  247. {
  248.   REAL hours, degrees;
  249.  
  250.   hours   = (REAL)(ptr->rah)  + (REAL)(ptr->ram)  / (REAL)60.0;
  251.   degrees = (REAL)(ptr->decd) + (REAL)(ptr->decm) / (REAL)60.0;
  252.  
  253.   *raptr = CONV * (REAL)15.0 * hours;
  254.   if (*raptr >= TWO_PI) *raptr = ZERO;
  255.  
  256.   *decptr = CONV * degrees;
  257.   if (!ptr->isn) *decptr = -(*decptr);
  258.   if (*decptr >  PIby2) *decptr =  PIby2;
  259.   if (*decptr < -PIby2) *decptr = -PIby2;
  260.  
  261.   return;
  262. }
  263.  
  264. /********************************************************/
  265. /*                 List-Building Function               */
  266. /********************************************************/
  267. static void userobj_buildfn(void)
  268. {
  269.   plotobj userobj;
  270.  
  271. /* Bounding box of plotting symbol, relative to         */
  272. /* position of symbol:                                  */
  273.   static wimp_box size = {-12, -12, 14, 14};
  274.  
  275. /* Choose to keep plotting list up-to-date with all     */
  276. /* changes in Observer details, so omit check on        */
  277. /* whether module is enabled or not.                    */
  278.  
  279. /* Any pending rebuild request is now being met.        */
  280.   request_pending = FALSE;
  281.  
  282. /*Build plotobj for the one object owned by this module.*/
  283.     userobj.id = 0;
  284.     userobj.module = moduleid;
  285.     userobj.plotfn  = userobj_plotfn;
  286.     radec_altaz(ra, dec, &ob_data, ob_data.sid, &userobj.alt, &userobj.azim);
  287.     userobj.size = size;
  288.  
  289.     /* Offer this to the main program.                  */
  290.     addobj(userobj, &horiz_id, &vert_id);
  291.  
  292.   return;
  293. }
  294.  
  295.  
  296. /********************************************************/
  297. /*              Object-Selecting Function               */
  298. /********************************************************/
  299. static void userobj_selectfn(selectfn_reasoncode reason)
  300. {
  301.  
  302.   switch (reason)
  303.   {
  304.     case new_selection:
  305.       /* Only one User Object, so selection always      */
  306.       /* succeeds.                                      */
  307.       selection.id = 0;
  308.       selection.selected_OK = TRUE;
  309.     case window_selection:
  310.       /* A selection has been made by clicking in a     */
  311.       /* window.                                        */
  312.     case recalculate_data:
  313.       /* Observer details have changed, and plotting    */
  314.       /* lists have been rebuilt.                       */
  315.       /*                                                */
  316.       /* Fill in details of rising, setting etc.        */
  317.       selection_details();
  318.       break;
  319.  
  320.     case timeonly_recalculate:
  321.       /* As recalculate_data, but only the time of day  */
  322.       /* (and possibly the direction of view - this is  */
  323.       /* is of no interest) have changed.               */
  324.       /* This simplifies the calculation.               */
  325.       selection.horiz_id    = horiz_id;
  326.       selection.vert_id     = vert_id;
  327.       /* Decide if it can be seen now.                  */
  328.       selection.now         = selection.horiz_id != NOWHERE || \
  329.                               selection.vert_id  != NOWHERE;
  330.       break;
  331.  
  332.     case sel_info_request:
  333.       /* Write info into text buffer.   Use Info fn.    */
  334.       userobj_infofn(0);
  335.       break;
  336.  
  337.     default:
  338.       /* Unknown option.  Do nothing.                   */
  339.       break;
  340.  
  341.     }
  342.  
  343.   return;
  344. }
  345.  
  346. /*------------------------------------------------------*/
  347. /*  Function to fill in selection details of selected   */
  348. /* User Object (viewing directions and times for rising,*/
  349. /*             setting, culminating etc).               */
  350. /*------------------------------------------------------*/
  351. static void selection_details(void)
  352. {
  353.   double ch;    /* cos of hour angle at horizon.        */
  354.   BOOL riset;   /* Whether object rises & sets or not.  */
  355.   BOOL culmin;  /* Whether object culminates or not.    */
  356.  
  357. /* Record window IDs of User Object.                    */
  358.   selection.horiz_id    = horiz_id;
  359.   selection.vert_id     = vert_id;
  360.  
  361. /* Find out if it can be seen now.                      */
  362.   selection.now         = selection.horiz_id != NOWHERE || \
  363.                           selection.vert_id  != NOWHERE;
  364.  
  365. /* Find out if Object rises, sets or culminates today.  */
  366. /* (After setting effective altitude of horizon.)       */
  367.   radec_sethoriz(HORALT);
  368.  
  369.   radec_phenomena(ra, dec, &ob_data, &ch, &riset, &culmin);
  370.   selection.rising      = riset;
  371.   selection.setting     = riset;
  372.   selection.culminating = culmin;
  373.  
  374. /* Fill in details for each phenomenon which occurs.    */
  375.  
  376.   if (selection.rising)
  377.     radec_rise_details(ra, dec, &ob_data, ch,
  378.         &selection.rise_azim,
  379.         &selection.rise_hour,
  380.         &selection.rise_min);
  381.  
  382.   if (selection.setting)
  383.     radec_set_details(ra, dec, &ob_data, ch,
  384.         &selection.set_azim,
  385.         &selection.set_hour,
  386.         &selection.set_min);
  387.  
  388.   if (selection.culminating)
  389.     radec_cul_details(ra, dec, &ob_data,
  390.         &selection.cul_alt,
  391.         &selection.cul_azim,
  392.         &selection.cul_hour,
  393.         &selection.cul_min);
  394.  
  395.   return;
  396. }
  397.  
  398. /********************************************************/
  399. /*                   Display Function                   */
  400. /********************************************************/
  401. static BOOL userobj_displayfn(BOOL *enabptr)
  402. {
  403.   BOOL changes;
  404.  
  405. /* Respond to click on Display menu entry,  or to move- */
  406. /* ment of pointer over arrow on menu entry.            */
  407.  
  408. /* Find out whether or not event was a menu choice.     */
  409.   if (wimpt_last_event()->e == wimp_EMENU)
  410.   {
  411. /* Menu choice.                                         */
  412.   /* Toggle Enable/Disable flag.                        */
  413.     display_flag = !display_flag;
  414.  
  415.   /* Inform main program of new status.                 */
  416.     *enabptr = display_flag;
  417.  
  418.   /* Issue a Rebuild Request if one is pending.         */
  419.     rebuild_request = request_pending;
  420.  
  421.   /* Windows will always need updating.                 */
  422.     return TRUE;
  423.   }
  424.  
  425. /* User has invoked Display dialogue box.               */
  426. /* Create dialogue box, load it with data, and put it   */
  427. /* on display (if not already done).                    */
  428.   if (!dbox_persisting)
  429.   {
  430.     d_disp = dbox_new(DISPBOX_NAME);
  431.     if (d_disp == NULL) return FALSE;
  432.     load_dispbox(¤t_data);
  433.     dbox_show(d_disp);
  434.   }
  435.  
  436. /* Deal with clicks on buttons until action by main     */
  437. /* program is required.  Fn returns TRUE if changes     */
  438. /* affecting the appearance of the windows have been    */
  439. /* made.                                                */
  440.   changes = dispbox_buttons();
  441.  
  442. /* Delete disp box if it is not required to persist.    */
  443.   if (!dbox_persisting) dbox_dispose(&d_disp);
  444.  
  445. /* Plotting lists will need rebuilding if significant   */
  446. /* changes have been made.                              */
  447. /* If module is currently enabled, issue request now.   */
  448. /* If not, make a note that a request is pending.       */
  449.   rebuild_request = (changes || request_pending) &&  display_flag;
  450.   request_pending = (changes || request_pending) && !display_flag;
  451.  
  452. /* Windows will need updating if and only if plotting   */
  453. /* lists need rebuilding.                               */
  454.   return rebuild_request;
  455. }
  456.  
  457. /*------------------------------------------------------*/
  458. /*  Function to load dbox with data pointed to by ptr.  */
  459. /*------------------------------------------------------*/
  460. static void load_dispbox(userobjstr *ptr)
  461. {
  462.   char numbuf[16];
  463.  
  464. /* Right Ascension (hour part, then minute part):       */
  465.   sprintf(numbuf, "%02.2i", ptr->rah);
  466.   dbox_setfield(d_disp, rah_field, numbuf);
  467.   sprintf(numbuf, "%02.2i", ptr->ram);
  468.   dbox_setfield(d_disp, ram_field, numbuf);
  469.  
  470. /* Declination (degrees, then minutes, then North/South)*/
  471.   sprintf(numbuf, "%02.2i", ptr->decd);
  472.   dbox_setfield(d_disp, decd_field, numbuf);
  473.   sprintf(numbuf, "%02.2i", ptr->decm);
  474.   dbox_setfield(d_disp, decm_field, numbuf);
  475.   dbox_setfield(d_disp, ns_field, (ptr->isn ? "N" : "S"));
  476.  
  477. /* Three lines of text:                                 */
  478.   dbox_setfield(d_disp, text1_field, ptr->text1);
  479.   dbox_setfield(d_disp, text2_field, ptr->text2);
  480.   dbox_setfield(d_disp, text3_field, ptr->text3);
  481.  
  482.   return;
  483. }
  484.  
  485. /*------------------------------------------------------*/
  486. /*  Function to read the data in the Display dbox, and  */
  487. /*    copy them to the userobjstr pointed to by ptr.    */
  488. /*------------------------------------------------------*/
  489. static void read_dispbox(userobjstr *ptr)
  490. {
  491.   char nsbuf[2];
  492.  
  493. /* Right Ascension (hour part, then minute part):       */
  494.   ptr->rah = dbox_getnumeric(d_disp, rah_field);
  495.   ptr->ram = dbox_getnumeric(d_disp, ram_field);
  496.  
  497. /* Declination (degrees, minutes, North / South):       */
  498.   ptr->decd = dbox_getnumeric(d_disp, decd_field);
  499.   ptr->decm = dbox_getnumeric(d_disp, decm_field);
  500.   dbox_getfield(d_disp, ns_field, nsbuf, 2);
  501.   ptr->isn = (nsbuf[0] == 'N');
  502.  
  503. /* Three lines of text:                                 */
  504.   dbox_getfield(d_disp, text1_field, ptr->text1, USEROBJ_TEXTLEN);
  505.   dbox_getfield(d_disp, text2_field, ptr->text2, USEROBJ_TEXTLEN);
  506.   dbox_getfield(d_disp, text3_field, ptr->text3, USEROBJ_TEXTLEN);
  507.  
  508.   return;
  509. }
  510.  
  511. /*------------------------------------------------------*/
  512. /* Function to handle clicks on buttons in Display dbox.*/
  513. /* Returns TRUE if changes have been made which require */
  514. /*           the re-drawing of the windows.             */
  515. /*------------------------------------------------------*/
  516. static BOOL dispbox_buttons(void)
  517. {
  518.   int response;          /* Button No. clicked by user. */
  519.   BOOL changes;          /* TRUE if significant changes.*/
  520.   userobjstr temp_data;  /* Temp store for dbox data.   */
  521.  
  522. /* Loop until user clicks on OK, or on Cancel with left */
  523. /* hand mouse button, or destroys dbox by (eg) clicking */
  524. /* outside it.                                          */
  525.  
  526.   while (TRUE)
  527.   {
  528.  
  529.   /* Get button number of latest click.                 */
  530.     response = dbox_fillin(d_disp);
  531.  
  532.   /* Take appropriate action.                           */
  533.     switch (response) {
  534.  
  535.       case box_destroy:
  536.       /* Box destroyed.  Close it & return.             */
  537.         dbox_persisting = FALSE;
  538.         return FALSE;
  539.  
  540.       case ok_butt:
  541.       /* Read data in dbox.                             */
  542.         read_dispbox(&temp_data);
  543.       /* Copy to current_data, noting whether there have*/
  544.       /* been any changes requiring the re-drawing of   */
  545.       /* the windows.                                   */
  546.         changes = copy_data(&temp_data, ¤t_data);
  547.         dbox_persisting = dbox_persist();
  548.       /* Can safely ignore clicks with Adjust when no   */
  549.       /* significant changes have been made.            */
  550.         if (dbox_persisting && !changes) break;
  551.       /* Calc new RA and Dec, if necessary.             */
  552.         if (changes) userobj_radec(¤t_data, &ra, &dec);
  553.         return changes;
  554.  
  555.       case cancel_butt:
  556.       /* If click was with Select, close dbox & return. */
  557.         if (!dbox_persist())
  558.         { dbox_persisting = FALSE;
  559.           return FALSE; }
  560.       /* If Adjust, reload current data and continue    */
  561.       /* looping.                                       */
  562.         load_dispbox(¤t_data);
  563.         break;
  564.  
  565.       case show_butt:
  566.       /* Load default settings from disc.   If error,   */
  567.       /* report it and continue; else display new values*/
  568.         if (!read_discfile(&temp_data))
  569.           werr(NON_FATAL, "Can't load defaults");
  570.         else
  571.           load_dispbox(&temp_data);
  572.         break;
  573.  
  574.       case set_butt:
  575.       /* Save dbox settings to disc.  If error, report  */
  576.       /* it & continue looping.                         */
  577.         read_dispbox(&temp_data);
  578.         if (!write_discfile(&temp_data))
  579.         { werr(NON_FATAL, "Can't set defaults");
  580.           break; }
  581.       /* If click was with Select, close dbox and       */
  582.       /* return (no need to re-draw windows). If Adjust,*/
  583.       /* continue looping.                              */
  584.         if (!dbox_persist())
  585.         { dbox_persisting = FALSE;
  586.           return FALSE; }
  587.         break;
  588.  
  589.       default:
  590.       /* One of the data-changing buttons.              */
  591.         dispbox_databutts(response);
  592.         break;
  593.  
  594.     }
  595.   }
  596. }
  597.  
  598. /*------------------------------------------------------*/
  599. /*    Function to handle clicks on the data-changing    */
  600. /*         buttons in the Display dialogue box.         */
  601. /*------------------------------------------------------*/
  602. static void dispbox_databutts(int response)
  603. {
  604.   char numbuf[16];
  605.   char ns_buf[2];
  606.   int hours, minutes, degrees;
  607.  
  608.   switch (response) {
  609.  
  610.     case rah_tu: case rah_td: case rah_uu: case rah_ud:
  611.     /* Change Hour part of Right Ascension.             */
  612.       hours = dbox_getnumeric(d_disp, rah_field);
  613.       hours += addon[response - rah_tu];
  614.       if (hours >= 0  &&  hours < 24)
  615.       {
  616.         sprintf(numbuf, "%02.2i", hours);
  617.         dbox_setfield(d_disp, rah_field, numbuf);
  618.       }
  619.       break;
  620.  
  621.     case ram_tu: case ram_td: case ram_uu: case ram_ud:
  622.     /* Change Minute part of Right Ascension.           */
  623.       minutes = dbox_getnumeric(d_disp, ram_field);
  624.       minutes += addon[response - ram_tu];
  625.       if (minutes >= 0  &&  minutes < 60)
  626.       {
  627.         sprintf(numbuf, "%02.2i", minutes);
  628.         dbox_setfield(d_disp, ram_field, numbuf);
  629.       }
  630.       break;
  631.  
  632.     case decd_tu: case decd_td: case decd_uu: case decd_ud:
  633.     /* Change Degree part of Declination.               */
  634.       degrees  = dbox_getnumeric(d_disp, decd_field);
  635.       degrees += addon[response - decd_tu];
  636.       minutes  = dbox_getnumeric(d_disp, decm_field);
  637.       if ((degrees >=  0  &&  degrees <  90) ||
  638.           (degrees == 90  &&  minutes ==  0))
  639.       {
  640.         sprintf(numbuf, "%02.2i", degrees);
  641.         dbox_setfield(d_disp, decd_field, numbuf);
  642.       }
  643.       break;
  644.  
  645.     case decm_tu: case decm_td: case decm_uu: case decm_ud:
  646.     /* Change Minute part of Declination.               */
  647.       minutes  = dbox_getnumeric(d_disp, decm_field);
  648.       minutes += addon[response - decm_tu];
  649.       if (minutes >=  0  &&  minutes <  60)
  650.       {
  651.         sprintf(numbuf, "%02.2i", minutes);
  652.         dbox_setfield(d_disp, decm_field, numbuf);
  653.       }
  654.       break;
  655.  
  656.     case ns_butt: case ns_field:
  657.     /* Toggle North / South setting.                    */
  658.       dbox_getfield(d_disp, ns_field, ns_buf, 2);
  659.       ns_buf[0] = (ns_buf[0] == 'N' ?  'S' : 'N' );
  660.       dbox_setfield(d_disp, ns_field, ns_buf);
  661.       break;
  662.  
  663.     default:
  664.     /* Unknown response.  Do nothing.                   */
  665.       break;
  666.  
  667.   }
  668.   return;
  669. }
  670.  
  671. /*------------------------------------------------------*/
  672. /*   Function to check whether two userobjstrs differ   */
  673. /*  significantly (ie in a way which would require the  */
  674. /*  windows to be re-drawn) and then copy the contents  */
  675. /*                of one into the other.                */
  676. /*------------------------------------------------------*/
  677. static BOOL copy_data(userobjstr *ptr1, userobjstr *ptr2)
  678. {
  679.   BOOL changes;
  680.  
  681.   changes = ptr1->rah  != ptr2->rah   ||
  682.             ptr1->ram  != ptr2->ram   ||
  683.             ptr1->decd != ptr2->decd  ||
  684.             ptr1->decm != ptr2->decm  ||
  685.            ( ptr1->isn && !ptr2->isn) ||
  686.            (!ptr1->isn &&  ptr2->isn);
  687.  
  688.   *ptr2 = *ptr1;
  689.  
  690.   return changes;
  691. }
  692.  
  693.  
  694. /********************************************************/
  695. /*                   Plotting Function                  */
  696. /********************************************************/
  697. static os_error *userobj_plotfn(int x, int y, int id)
  698. {
  699.   return sv_plotsprite(&spr_id, MODE_20, x, y, 5, 5);
  700. }
  701.  
  702.  
  703. /********************************************************/
  704. /*                     Info Function                    */
  705. /********************************************************/
  706. static void userobj_infofn(int id)
  707. {
  708.   sprintf(infoptr,
  709.           "User Object\nRA %02ih %02im   Dec %02i° %02i' %c\n%s\n%s\n%s",
  710.           current_data.rah,
  711.           current_data.ram,
  712.           current_data.decd,
  713.           current_data.decm,
  714.          (current_data.isn ? 'N' : 'S'),
  715.           current_data.text1,
  716.           current_data.text2,
  717.           current_data.text3);
  718.  
  719.   return;
  720. }
  721.